package osm_to_speedsigns;

// converts osm maxspeed way tags into discrete speedsigns in kml format
// and generates an image in png format
// copyright Simon Walters Oct 2010
// released under GPL V3

import java.awt.*;
//import java.awt.event.*;

import javax.imageio.ImageIO;
import javax.swing.*;

import java.io.*;
//import java.util.*;

import java.io.BufferedWriter;
import java.io.BufferedReader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
//import java.lang.reflect.Array;
//import java.lang.reflect.Array;
//import java.text.DateFormat;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
//import java.util.Date;
import java.util.StringTokenizer;

import org.w3c.dom.*;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;

import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

//import java.awt.*;
//import java.awt.event.*;
//import javax.swing.*;

//import java.awt.*;
//import java.awt.event.*;
import java.awt.image.BufferedImage;

//import javax.swing.*;
import javax.swing.filechooser.FileSystemView;

//import java.io.*;
//import java.util.*;


//import java.io.File;
//import java.io.FileReader;
//import java.io.IOException;
import javax.swing.JFileChooser;




class MyCustomFilter extends javax.swing.filechooser.FileFilter {
    @Override
    public boolean accept(File file) {
        return file.isDirectory() || file.getAbsolutePath().endsWith(".osm");
    }
    @Override
    public String getDescription() {

        return "OSM Map Files (*.osm)";
    }
}
/**
 *
 * @author teacher
 */
public class osm_to_speedsigns extends javax.swing.JFrame implements Runnable {
	
    // Variables declaration - do not modify
    private javax.swing.JMenuItem Exit;
    private javax.swing.JButton cancelBtn;
    private javax.swing.JFileChooser fileChooser;
    private javax.swing.JLabel fileLabel;
    private static javax.swing.JTextField fileTextField;
    private javax.swing.JLabel folderLabel;
    private static javax.swing.JTextField folderTextField;
    private javax.swing.JCheckBox jCheckBox1;
    private static javax.swing.JLabel myLabel;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JButton okBtn;
    private javax.swing.JMenuItem select;
	private JScrollPane jScrollPane1;
	private static JCheckBox jAutoResidential;
	private static JCheckBox jAutoMotorway;
	private JLabel jLabel1;
	private JLabel jLabel2;
	private static JProgressBar jProgressBar1;
	private static JTextArea infoTextArea;
    // End of variables declaration
    public static String dirName;
    
	public static String filePartName; 
	public static String longPartName;
	public static String latPartName;

	public static String filenameChoice;
	private static double lhEdge;
	private static double botEdge;
	public static ArrayList<Mappoint> mapPoints = new ArrayList<Mappoint>();
	public static ArrayList<String> ways = new ArrayList<String>();
	public static ArrayList<String> eliminate = new ArrayList<String>();
	public static ArrayList<String> speedSigns = new ArrayList<String>();
	
	public static int[] palette = new int[150];
	public static int[] kmlPalette = new int[150];
	
	
	private static BufferedImage image;
	private static Graphics g;
	private static int imageScale = 640;
	private static Graphics2D g2d;
	private static ImageIcon myImage;
	private static BufferedImage tiledImage;
	private static int divisions = 2;


    /** Creates new form JFileChooserDemo */
    public osm_to_speedsigns() {
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
 //   @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        fileChooser = new javax.swing.JFileChooser();
        fileLabel = new javax.swing.JLabel();
        fileTextField = new javax.swing.JTextField();
        folderLabel = new javax.swing.JLabel();
        folderTextField = new javax.swing.JTextField();
        jCheckBox1 = new javax.swing.JCheckBox();
        okBtn = new javax.swing.JButton();
        cancelBtn = new javax.swing.JButton();
        myLabel = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        infoTextArea = new javax.swing.JTextArea();
        jProgressBar1 = new javax.swing.JProgressBar();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jAutoResidential = new javax.swing.JCheckBox();
        jAutoMotorway = new javax.swing.JCheckBox();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        select = new javax.swing.JMenuItem();
        Exit = new javax.swing.JMenuItem();

        fileChooser.setDialogTitle("My dialog box");
        fileChooser.setFileFilter(new MyCustomFilter());

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Default Demo");

        fileLabel.setText("OSM Map Name:");

        fileTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                fileTextFieldActionPerformed(evt);
            }
        });

        folderLabel.setText("Folder:");

        jCheckBox1.setText("Process all .osm files in folder");
        jCheckBox1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jCheckBox1StateChanged(evt);
            }
        });

        okBtn.setText("OK");
        okBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okBtnActionPerformed(evt);
            }
        });

        cancelBtn.setText("Cancel");

        myLabel.setBackground(new java.awt.Color(128, 128, 128));
        myLabel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        myLabel.setMaximumSize(new java.awt.Dimension(320, 320));
        myLabel.setMinimumSize(new java.awt.Dimension(320, 320));
//        myLabel.addContainerListener(new java.awt.event.ContainerAdapter() {
//            public void componentAdded(java.awt.event.ContainerEvent evt) {
//                myLabelComponentAdded(evt);
//            }
//       });

        infoTextArea.setColumns(20);
        infoTextArea.setRows(5);
        jScrollPane1.setViewportView(infoTextArea);

        jLabel1.setText("Map Image");

        jLabel2.setText("Progress Information");

        jAutoResidential.setText("Auto-include Residential Highways");

        jAutoMotorway.setText("Auto-include Motorways");

        jMenu1.setText("File");

        select.setText("Select File");
        select.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectActionPerformed(evt);
            }
        });
        jMenu1.add(select);

        Exit.setText("Exit");
        Exit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ExitActionPerformed(evt);
            }
        });
        jMenu1.add(Exit);

        jMenuBar1.add(jMenu1);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(folderLabel)
                            .addComponent(fileLabel))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                .addComponent(folderTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 441, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(40, 40, 40))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                        .addComponent(okBtn)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(cancelBtn))
                                    .addComponent(fileTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 187, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGap(294, 294, 294)))
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jAutoResidential)
                            .addComponent(jCheckBox1)
                            .addComponent(jAutoMotorway)))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(myLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel1))
                        .addGap(52, 52, 52)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 385, Short.MAX_VALUE)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 385, Short.MAX_VALUE)
                            .addComponent(jLabel2))
                        .addContainerGap())))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(folderLabel)
                    .addComponent(folderTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jCheckBox1))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(fileLabel)
                    .addComponent(fileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jAutoResidential))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(okBtn)
                    .addComponent(cancelBtn)
                    .addComponent(jAutoMotorway))
                .addGap(19, 19, 19)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(myLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 299, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

		image = new BufferedImage(imageScale, imageScale, BufferedImage.TYPE_INT_RGB); 
		tiledImage = new BufferedImage((imageScale / divisions), (imageScale / divisions), BufferedImage.TYPE_INT_RGB); 
		g = image.getGraphics();  
		g.setColor(new Color(255, 255, 255) );
		g.fillRect ( 0, 0, image.getWidth(), image.getHeight() );
		for (int y =0;y<imageScale;y+=2) {
			for (int x =0;x<imageScale;x+=2) {
//				image.setRGB(x, y, 0xE0E0E0);
			}
		}
		g2d = (Graphics2D)g;
		
		myImage = new ImageIcon(image); // .getScaledInstance(1280, 1280, 1));

		myLabel.setIcon(myImage);
		this.add(myLabel);
		myLabel.setVisible(true);

		fileTextField.setText("map_w0027_n0536.osm");
        pack();
    }// </editor-fold>

    private void selectActionPerformed(java.awt.event.ActionEvent evt) {
        int returnVal = fileChooser.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();
 //           try {
              // What to do with the file, e.g. display it in a TextArea
               folderTextField.setText(file.getParent());
               dirName=folderTextField.getText();
               fileTextField.setText(file.getName());
 //              textarea.read( new FileReader( file.getAbsolutePath() ), null );
 //           } catch (IOException ex) {
 //             System.out.println("problem accessing file"+file.getAbsolutePath());
 //           }
        } else {
            System.out.println("File access cancelled by user.");
        }

    }

    private void ExitActionPerformed(java.awt.event.ActionEvent evt) {
        System.exit(0);
    }

    private void fileTextFieldActionPerformed(java.awt.event.ActionEvent evt) {
    	
    }
    
    private void jCheckBox1StateChanged(javax.swing.event.ChangeEvent evt) {
        if (jCheckBox1.isSelected()) {
            fileTextField.setEnabled(false);
            fileLabel.setEnabled(false);
        } else {
            fileTextField.setEnabled(true);
            fileLabel.setEnabled(true);
        }
    }

    private void okBtnActionPerformed(java.awt.event.ActionEvent evt) {
    	Thread worker = new Thread(this);
    	worker.start();  // this calls the method run()
    }
    
	@SuppressWarnings("unchecked")
	@Override
	public void run() {
		Properties props = new Properties();
		try {
            JFileChooser fr = new JFileChooser();
            FileSystemView fw = fr.getFileSystemView();
            String dirNameProps = fw.getDefaultDirectory().getAbsolutePath();
			props.load(new FileInputStream(dirNameProps + "/palette.props"));
			Enumeration en = props.propertyNames();
		    while (en.hasMoreElements()) {
		      String key = (String) en.nextElement();
		      palette[Integer.parseInt(key)] =Integer.parseInt(props.getProperty(key),16);
		      kmlPalette[Integer.parseInt(key)]=(palette[Integer.parseInt(key)]&0xFF000000) + ((palette[Integer.parseInt(key)]&0x00FF0000)>>16) + ((palette[Integer.parseInt(key)]&0x0000FF00)) + ((palette[Integer.parseInt(key)]&0x000000FF)<<16);
		    }
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}


        if (jCheckBox1.isSelected()) {
            ProcessAllOSMFiles();
        } else {
            ProcessSingleOSMFile();
        }
        AddToInfo("=== Finished Processing ===");
	}   		



    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
	            JFileChooser fr = new JFileChooser();
	            FileSystemView fw = fr.getFileSystemView();
	            dirName = fw.getDefaultDirectory().getAbsolutePath();
	            new osm_to_speedsigns().setVisible(true);
	            folderTextField.setText(dirName);
	            File logFile = new File(dirName +"/map_" + filePartName + ".log");
	            @SuppressWarnings("unused")
				PrintStream printStream;
				try {
					printStream = new PrintStream(new FileOutputStream(logFile)); 
//					System.setOut(printStream);
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}

            }
        });
    }

    public static void ProcessAllOSMFiles() {
		String stringDir = dirName +"/";
		int stringDirLen = stringDir.length();
		File file = new File(stringDir);  
		File[] files = file.listFiles();  
		 for (int fileInList = 0; fileInList < files.length; fileInList++)  {  
			 String checkFile = files[fileInList].toString().substring(stringDirLen);
			 int lenCheckFile = Math.max(4,checkFile.length());
			 if (lenCheckFile > 4){
				 if (checkFile.substring(lenCheckFile-4,lenCheckFile).equals(".osm")) {
					 if (checkFile.substring(0,4).equals("map_")) {
						System.out.println(checkFile); 
						fileTextField.setText(checkFile);
						filePartName = checkFile.substring(4,15);
			            File logFile = new File(dirName +"/map_" + filePartName + ".log");
			            PrintStream printStream;
						try {
							printStream = new PrintStream(new FileOutputStream(logFile)); 
							System.setOut(printStream);
						} catch (FileNotFoundException e) {
							e.printStackTrace();
						}
						AddToInfo("Processing: "+filePartName); 
						convertOSM();
					 }
				}
			 }

		 }
    }


    public void ProcessSingleOSMFile() {
        filenameChoice = fileTextField.getText().substring(4, 15);

		System.out.println("\n" + filenameChoice);
		filePartName = filenameChoice;
		jProgressBar1.setIndeterminate(true);
		convertOSM();

    }
    


	public static void convertOSM() {
		System.out.println("Checking for: " + dirName + "\\map_" + filePartName + ".osm");
		File checkFile = new File(dirName + "\\map_" + filePartName + ".osm");
		if (checkFile.exists()) {
			g.setColor(new Color(255, 255, 255) );
			g.fillRect ( 0, 0, image.getWidth(), image.getHeight() );
			
			lhEdge = Double.valueOf(filePartName.substring(1, 5)) / 10;
			botEdge = Double.valueOf(filePartName.substring(7, 11)) / 10;
			if ((filePartName.substring(0, 1)).equals("w")) {
				lhEdge *= -1;
			}
			if ((filePartName.substring(0, 1)).equals("s")) {
				botEdge *= -1;
			}
			mapPoints.clear();
			ways.clear();
			eliminate.clear();
			speedSigns.clear();
			jProgressBar1.setIndeterminate(true);
			jProgressBar1.setVisible(true);
			
			AddToInfo("Converting osm nodes into database of long/lat");
			ReadAndSaveMapNodes();
			AddToInfo("Finished Converting osm nodes into database of long/lat");
			
			AddToInfo("Reading Map Points into Arraylist");
			readMapPoints();
			AddToInfo("Finised Reading Map Points into Arraylist");
			
			AddToInfo("Start Reading Highways and make csv");			
			ReadAndSaveHighways();
			AddToInfo("Finished Reading Highways and make csv");
			
			AddToInfo("Start Reading Ways and make csv");
			ReadAndSaveWayMaxspeeds();
			AddToInfo("Finished Reading Ways and make csv");
					
			AddToInfo("Read ways back from csv and Initialise Eliminate");
			InitialiseEliminate();
			AddToInfo("Finished Initialising Eliminate");
	
			AddToInfo("Start Elimating Duplicate Way Nodes");
			GenerateSpeedSignData();
			AddToInfo("Finished Elimating Duplicate Way Nodes");
	
			AddToInfo("Start Adding T Junctions");
//			AddTJunctionSigns();
			AddToInfo("Finished Adding T Junctions");
			
			AddToInfo("Start Making Map");
			MakeMap();
			AddToInfo("Finished Making Map");
			
			AddToInfo("Cut into tiles");
			MakeTiles();
			AddToInfo("...done");
	
			AddToInfo("Start Writing KML File");
			WriteKMLFile();
			AddToInfo("Finished Writing KML File: " + filePartName);
			

			BufferedWriter bw;
			try {
				String mapNodes = dirName+ "/mapmaxspeeds2_" + filePartName + ".csv";
				@SuppressWarnings("unused")
				boolean success = (new File(mapNodes)).delete();
				bw = new BufferedWriter(new FileWriter(mapNodes, true), 8);
	
				for (int mainLoop = 0; mainLoop < (ways.size()); mainLoop++) {
//					System.out.println(mainLoop + ": " + eliminate.get(mainLoop)+ "," + ways.get(mainLoop));
					bw.write(mainLoop + "," + eliminate.get(mainLoop)+ "," + ways.get(mainLoop));
					bw.newLine();
				}
				bw.flush();
				bw.close();
	
			} catch (Throwable t) {
				t.printStackTrace();
			}
		} else {
			infoTextArea.append("\nFile does not exist!\n");
		}
		jProgressBar1.setIndeterminate(false);
		jProgressBar1.setVisible(false);
//		System.exit(0);
	}

	// Ream XLM File
	public static void ReadAndSaveMapNodes() {

		BufferedWriter bw;

		String osmFilename = dirName +"/map_" + filePartName + ".osm";
		String lastModifiedFilename = dirName + "/lastmodnodes_" + filePartName + ".txt";
		try {
			Long currentMapNodesModified = (long)1;
			Long previousMapNodesModified = (long)2;
			
			try {
				File checkFile = new File(osmFilename);
				currentMapNodesModified = checkFile.lastModified();

				
				BufferedReader bufRdr = new BufferedReader(new FileReader(lastModifiedFilename));
				String prevLastMod = bufRdr.readLine();
				bufRdr.close();
				previousMapNodesModified = Long.parseLong(prevLastMod);

			} catch (Throwable t) {
				t.printStackTrace();
			}
			
			if (previousMapNodesModified.compareTo(currentMapNodesModified) ==  0) {
				return;
			}
			
			String mapNodes = dirName + "/mapnodes_" + filePartName + ".csv";
			@SuppressWarnings("unused")
			boolean success2 = (new File(mapNodes)).delete();
			bw = new BufferedWriter(new FileWriter(mapNodes, true), 8);

			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
			Document doc = docBuilder.parse(new File(osmFilename));

			// normalize text representation
			doc.getDocumentElement().normalize();
			System.out.println("Root element of the doc is "
					+ doc.getDocumentElement().getNodeName());

			NodeList listOfMapPoints = doc.getElementsByTagName("node");
			int totalMapPoints = listOfMapPoints.getLength();
			System.out.println("Total no of MapPoints : " + totalMapPoints);
			jProgressBar1.setMaximum(totalMapPoints);
			jProgressBar1.setIndeterminate(false);
			jProgressBar1.setStringPainted(true);
			for (int s = 0; s < listOfMapPoints.getLength(); s++) {
				jProgressBar1.setValue(s);
				String id = "";
				String lon = "";
				String lat = "";
				// System.out.print("MapPoint," + s);
				NamedNodeMap MapPointAttrs = listOfMapPoints.item(s)
						.getAttributes();

				for (int i = 0; i < MapPointAttrs.getLength(); i++) {
					if (MapPointAttrs.item(i).getNodeName().equals("id")) {
						id = MapPointAttrs.item(i).getNodeValue();
					}
					if (MapPointAttrs.item(i).getNodeName().equals("lon")) {
						lon = MapPointAttrs.item(i).getNodeValue();
					}
					if (MapPointAttrs.item(i).getNodeName().equals("lat")) {
						lat = MapPointAttrs.item(i).getNodeValue();
					}
				}
				String lineOut = id + "," + lon + "," + lat;
				System.out.println(s + ": " + lineOut);
				bw.write(lineOut);
				bw.newLine();
			}// end of for loop with s var
			bw.flush();
			bw.close();
			System.out.println("Finished");
			
			mapPoints.clear();
			readMapPoints();

			// create a KML file of nodes
			bw = null;
			String KMLmapNodes = dirName + "/mapnodes_"
					+ filePartName + ".kml";
			@SuppressWarnings("unused")
			boolean success = (new File(KMLmapNodes)).delete();
			bw = new BufferedWriter(new FileWriter(KMLmapNodes, true), 8);
			bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			bw.newLine();
			bw.write("<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\" xmlns:kml=\"http://www.opengis.net/kml/2.2\" xmlns:atom=\"http://www.w3.org/2005/Atom\">");
			bw.newLine();
			bw.write("<Document>\n");

			for (int nodeLoop = 0; nodeLoop < (mapPoints.size()); nodeLoop++) {

					System.out.println("KMLNode: "+ nodeLoop + ": " + mapPoints.get(nodeLoop));
					float lon = 0;
					float lat = 0;
					
					lon = mapPoints.get(nodeLoop).getlon();
					lat = mapPoints.get(nodeLoop).getlat();

					if ((lon >= lhEdge) && (lon < (lhEdge + 0.1))
							&& (lat >= botEdge) && (lat < (botEdge + 0.1))) {
						bw.write("<Placemark>\n\t<name>" + mapPoints.get(nodeLoop).getid()
								 + "</name>\n");
						bw.write("\t\t\n");
						bw.write("\t\t<Point>\n\t\t\t<coordinates>" + lon + ","
								+ lat + ",0</coordinates>\n\t\t</Point>\n");
						bw.write("</Placemark>");
						bw.newLine();
					}

			}// end of nodeLoop
			bw.write("</Document>\n");
			bw.write("</kml>");
			bw.flush();
			bw.close();
			
			// remember last modified file datetime
			@SuppressWarnings("unused")
			boolean success3 = (new File(lastModifiedFilename)).delete();
			bw = new BufferedWriter(new FileWriter(lastModifiedFilename, true), 8);
			bw.write(""+ (new File(osmFilename)).lastModified());
			bw.newLine();
			DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm");
			Date date = new Date((new File(osmFilename)).lastModified());
			bw.write(""+ dateFormat.format(date));
			bw.newLine();
			bw.flush();
			bw.close();
			

		} catch (SAXParseException err) {
			System.out.println("** Parsing error" + ", line "
					+ err.getLineNumber() + ", uri " + err.getSystemId());
			System.out.println(" " + err.getMessage());

		} catch (SAXException e) {
			Exception x = e.getException();
			((x == null) ? e : x).printStackTrace();

		} catch (Throwable t) {
			t.printStackTrace();
		}
		

		// System.exit (0);

	}// end of main
	
	// Read ways from osm file to find Highways
	public static void ReadAndSaveHighways() {

		BufferedWriter bw;
		try {
			String highwayCSVFilename = dirName + "/map_highways_"
					+ filePartName + ".csv";
			@SuppressWarnings("unused")
			boolean success = (new File(highwayCSVFilename)).delete();
			bw = new BufferedWriter(new FileWriter(highwayCSVFilename, true), 8);

			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
			Document doc = docBuilder.parse(new File(
					dirName + "/map_"
							+ filePartName + ".osm"));

			// normalize text representation
			doc.getDocumentElement().normalize();

			NodeList listOfWays = doc.getElementsByTagName("way");
			int totalWays = listOfWays.getLength();
			jProgressBar1.setIndeterminate(false);
			jProgressBar1.setMaximum(totalWays);
			System.out.println("Total no of Ways : " + totalWays);

			for (int s = 0; s < listOfWays.getLength(); s++) {
				jProgressBar1.setValue(s);
				jProgressBar1.setStringPainted(true);

				System.out.println("Way: " + s);
				boolean roundabout = false;
				String wayType = "";
				boolean maxspeedFound = false;
				boolean highwayFound = false;;
				
				int wayID = 0;
				String maxSpeed = "";
		//		String maxSpeedv = "";
				String oneway = "no";
				String lineOut = "";
				// System.out.print("MapPoint," + s);
				NamedNodeMap WaysAttrs = listOfWays.item(s).getAttributes();
				String username = "NOUSERFOUND";
				for (int i = 0; i < WaysAttrs.getLength(); i++) { // loop thru <way> attrs

					if (WaysAttrs.item(i).getNodeName().equals("id")) {
						wayID = Integer.parseInt(WaysAttrs.item(i)
								.getNodeValue());

					}
					if (WaysAttrs.item(i).getNodeName().equals("user")) {
						username = WaysAttrs.item(i).getNodeValue();
					}

				} // end loop thru <way> attrs
				lineOut = lineOut + wayID;
				lineOut = lineOut + "," + username;
				Element WaysElement = (Element) listOfWays.item(s);
				NodeList listOfWaysChildNodes = WaysElement.getChildNodes();
				System.out.println("Child Nodes: " + listOfWaysChildNodes.getLength());
				System.out.println("Scan for <tag> nodes");
				for (int i = 0; i < listOfWaysChildNodes.getLength(); i++) { // scan each <way> for <tag>s
					if (listOfWaysChildNodes.item(i).getNodeName().equals("tag")) {
						NamedNodeMap TagAttrs = listOfWaysChildNodes.item(i).getAttributes();
						for (int j = 0; j < TagAttrs.getLength(); j++) {

							if ((TagAttrs.item(j).getNodeValue()).equals("highway")) {
								highwayFound = true;
								if ((TagAttrs.item(j+1).getNodeValue()).equals("residential")) {
									if (maxSpeed.equals("")) {
										if (jAutoResidential.isSelected()) {
											maxspeedFound = true;
											maxSpeed = "30 mph";	
										}

									}
								}
							}
							
							if ((TagAttrs.item(j).getNodeValue()).equals("highway")) {
								if ((TagAttrs.item(j+1).getNodeValue()).equals("motorway")) {
									if (maxSpeed.equals("")) {
										if (jAutoMotorway.isSelected()) {
											maxspeedFound = true;
											maxSpeed = "70 mph";	
										}
										}
								}
							}


							if ((TagAttrs.item(j).getNodeValue())
									.equals("maxspeed")) {
								maxspeedFound = true;
								maxSpeed = TagAttrs.item(j + 1).getNodeValue();
								if (maxSpeed.equals("national") || maxSpeed.equals("nsl") ){
									maxSpeed = "60 mph";
								} else {
//									StringTokenizer st = new StringTokenizer(maxSpeedv," ");
//									maxSpeed = st.nextToken();
								}
								

							}
							if ((TagAttrs.item(j).getNodeValue())
									.equals("junction")) {
								if (TagAttrs.item(j + 1).getNodeValue().equals(
										"roundabout")) {
									roundabout = true;
									// System.out.println(roundabout);
								}
							}
							if ((TagAttrs.item(j).getNodeValue())
									.equals("oneway")) {
								if (TagAttrs.item(j + 1).getNodeValue().equals("yes")) {
									oneway = "yes";
									//System.out.println("\n OneWay");
								}
								if (TagAttrs.item(j + 1).getNodeValue().equals("true")) {
									oneway = "yes";
									//System.out.println("\n OneWay");
								}

							}
						}
					}
				} //end // scan each <way> for <tag>s
				if (maxSpeed.equals("50mph")) {
					maxSpeed = "50 mph";
				}
				if (maxSpeed.equals("4mph")) {
					maxSpeed = "40 mph";
				}
				if (maxspeedFound) {
					lineOut = lineOut + ",maxspeed," + maxSpeed;
				} else if (highwayFound) {
					lineOut = lineOut + ",highway,0 mph"; 
				}
				if (roundabout) {
					wayType = wayType + "roundabout";
				}
				if (wayType.isEmpty()) {
					wayType = "normal";
				}

				float lonLatPairs[][] = new float[4][2];
				int ndCount = 0;
				int nodestartends[] = new int[4];
				// loop thru way childnodes to find mappoint refs and lookup
				// lon/lat
				String nodelist = "";
				System.out.println("Child Nodes: " + listOfWaysChildNodes.getLength());
				System.out.println("Scan for <nd> nodes");
				for (int i = 0; i < listOfWaysChildNodes.getLength(); i++) {
					if (listOfWaysChildNodes.item(i).getNodeName().equals("nd")) {
						NamedNodeMap TagAttrs = listOfWaysChildNodes.item(i)
								.getAttributes();

						for (int j = 0; j < TagAttrs.getLength(); j++) {
							if ((TagAttrs.item(j).getNodeName()).equals("ref")) {
								// lineOut += "," + ndCount + "," +
								// Integer.parseInt(TagAttrs.item(j).getNodeValue());
								nodelist += " "
										+ TagAttrs.item(j).getNodeValue();
								if (ndCount == 0) {
									nodestartends[ndCount] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
									nodestartends[ndCount + 3] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
								} else if (ndCount == 1) {
									nodestartends[ndCount] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
									nodestartends[ndCount + 1] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
								}
								if (ndCount > 1) {
									nodestartends[3] = nodestartends[2];
									nodestartends[2] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
								}
								// lineOut += "," +
								// TagAttrs.item(j).getNodeValue();
							}// end checking for ref tags
						} // end looping thru nd tags
						ndCount += 1;
					}
				} // end loop thru way childnodes to find mappoint refs and
					// lookup lon/lat
				// lineOut += ",ndcount=" + ndCount;
				nodelist = nodelist.trim();
				for (ndCount = 0; ndCount < 4; ndCount++) {
					for (int k = 0; k < mapPoints.size(); k++) {
						if (mapPoints.get(k).getid() == nodestartends[ndCount]) {
							lonLatPairs[ndCount][0] = mapPoints.get(k).getlon();
							lonLatPairs[ndCount][1] = mapPoints.get(k).getlat();
							// lineOut = lineOut + "," +
							// mapPoints.get(k).getlon()+ "," +
							// mapPoints.get(k).getlat();
							// lineOut += "," + nodestartends[ndCount];
						}
					}
				}
				// Calc sign bearing

				double longDist;
				double latDist;
				double longDistDegrees = 0;
				double latDistDegrees = 0;
				longDistDegrees = (Double.valueOf(lonLatPairs[1][0])
						.doubleValue())
						- (Double.valueOf(lonLatPairs[0][0]).doubleValue());
				latDistDegrees = (Double.valueOf(lonLatPairs[1][1])
						.doubleValue())
						- (Double.valueOf(lonLatPairs[0][1]).doubleValue());

				longDist = (longDistDegrees * Math
						.cos((Float.valueOf(lonLatPairs[1][1]).floatValue()) * 3.1415926 / 180.0));
				latDist = (latDistDegrees);
				int angleToSign = (int) ((180 / 3.1415926) * Math.atan2(
						(double) latDist, (double) longDist));
				angleToSign = AngleToCompass(angleToSign);
				// int eduAngleToSign = Math.abs((int)((180/3.1415926) *
				// Math.atan2((double)latDist,(double)longDist)) - 90 +
				// Bearing);

				double longDist2;
				double latDist2;
				double longDistDegrees2 = 0;
				double latDistDegrees2 = 0;
				longDistDegrees2 = (Double.valueOf(lonLatPairs[3][0])
						.doubleValue())
						- (Double.valueOf(lonLatPairs[2][0]).doubleValue());
				latDistDegrees2 = (Double.valueOf(lonLatPairs[3][1])
						.doubleValue())
						- (Double.valueOf(lonLatPairs[2][1]).doubleValue());

				longDist2 = (longDistDegrees2 * Math
						.cos((Float.valueOf(lonLatPairs[1][1]).floatValue()) * 3.1415926 / 180.0));
				latDist2 = (latDistDegrees2);
				int angleToSign2 = (int) ((180 / 3.1415926) * Math.atan2(
						(double) latDist2, (double) longDist2));
				angleToSign2 = AngleToCompass(angleToSign2);

				// end calc sign bearing
				if ((highwayFound || maxspeedFound)) { // && (!roundabout))) { // && ((wayID
											// == 4119635) || (wayID ==
											// 4119634))) {
					String lineOutFinal = lineOut + "," + nodestartends[0]
							+ "," + nodestartends[1] + "," + angleToSign + ","
							+ AngleToDirection(angleToSign) + "," + wayType
							+ "," + nodelist + "," + nodestartends[2]+ "," + oneway;
					bw.write(lineOutFinal);
					System.out.println(s + ": " + lineOutFinal);
					bw.newLine();
				}

			}// end of for loop with s var
			bw.flush();
			bw.close();

		} catch (SAXParseException err) {
			System.out.println("** Parsing error" + ", line "
					+ err.getLineNumber() + ", uri " + err.getSystemId());
			System.out.println(" " + err.getMessage());

		} catch (SAXException e) {
			Exception x = e.getException();
			((x == null) ? e : x).printStackTrace();

		} catch (Throwable t) {
			t.printStackTrace();
		}

		

	}// end of read ways looking for highways

	
	

	// Read ways from osm file to find Maxspeeds
	public static void ReadAndSaveWayMaxspeeds() {

		BufferedWriter bw;
		try {
			String maxspeedCSVFilename = dirName + "/mapmaxspeeds_"
					+ filePartName + ".csv";
			@SuppressWarnings("unused")
			boolean success = (new File(maxspeedCSVFilename)).delete();
			bw = new BufferedWriter(new FileWriter(maxspeedCSVFilename, true), 8);

			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
			Document doc = docBuilder.parse(new File(
					dirName + "/map_"
							+ filePartName + ".osm"));

			// normalize text representation
			doc.getDocumentElement().normalize();

			NodeList listOfWays = doc.getElementsByTagName("way");
			int totalWays = listOfWays.getLength();
			jProgressBar1.setIndeterminate(false);
			jProgressBar1.setMaximum(totalWays);
			System.out.println("Total no of Ways : " + totalWays);

			for (int s = 0; s < listOfWays.getLength(); s++) {
				jProgressBar1.setValue(s);
				jProgressBar1.setStringPainted(true);

				System.out.println("Way: " + s);
				boolean roundabout = false;
				String wayType = "";
				boolean maxspeedFound = false;
				int wayID = 0;
				String maxSpeed = "";
		//		String maxSpeedv = "";
				String oneway = "no";
				String lineOut = "";
				// System.out.print("MapPoint," + s);
				NamedNodeMap WaysAttrs = listOfWays.item(s).getAttributes();
				String username = "NOUSERFOUND";
				for (int i = 0; i < WaysAttrs.getLength(); i++) { // loop thru <way> attrs

					if (WaysAttrs.item(i).getNodeName().equals("id")) {
						wayID = Integer.parseInt(WaysAttrs.item(i)
								.getNodeValue());

					}
					if (WaysAttrs.item(i).getNodeName().equals("user")) {
						username = WaysAttrs.item(i).getNodeValue();
					}

				} // end loop thru <way> attrs
				lineOut = lineOut + wayID;
				lineOut = lineOut + "," + username;
				Element WaysElement = (Element) listOfWays.item(s);
				NodeList listOfWaysChildNodes = WaysElement.getChildNodes();
				System.out.println("Child Nodes: " + listOfWaysChildNodes.getLength());
				System.out.println("Scan for <tag> nodes");
				for (int i = 0; i < listOfWaysChildNodes.getLength(); i++) { // scan each <way> for <tag>s
					if (listOfWaysChildNodes.item(i).getNodeName().equals("tag")) {
						NamedNodeMap TagAttrs = listOfWaysChildNodes.item(i).getAttributes();
						for (int j = 0; j < TagAttrs.getLength(); j++) {

							if ((TagAttrs.item(j).getNodeValue()).equals("highway")) {
								if ((TagAttrs.item(j+1).getNodeValue()).equals("residential")) {
									if (maxSpeed.equals("")) {
										if (jAutoResidential.isSelected()) {
											maxspeedFound = true;
											maxSpeed = "30 mph";	
										}

									}
								}
							}
							
							if ((TagAttrs.item(j).getNodeValue()).equals("highway")) {
								if ((TagAttrs.item(j+1).getNodeValue()).equals("motorway")) {
									if (maxSpeed.equals("")) {
										if (jAutoMotorway.isSelected()) {
											maxspeedFound = true;
											maxSpeed = "70 mph";	
										}
										}
								}
							}


							if ((TagAttrs.item(j).getNodeValue())
									.equals("maxspeed")) {
								maxspeedFound = true;
								maxSpeed = TagAttrs.item(j + 1).getNodeValue();
								if (maxSpeed.equals("national") || maxSpeed.equals("nsl") ){
									maxSpeed = "60 mph";
								} else {
//									StringTokenizer st = new StringTokenizer(maxSpeedv," ");
//									maxSpeed = st.nextToken();
								}
								

							}
							if ((TagAttrs.item(j).getNodeValue())
									.equals("junction")) {
								if (TagAttrs.item(j + 1).getNodeValue().equals(
										"roundabout")) {
									roundabout = true;
									// System.out.println(roundabout);
								}
							}
							if ((TagAttrs.item(j).getNodeValue())
									.equals("oneway")) {
								if (TagAttrs.item(j + 1).getNodeValue().equals("yes")) {
									oneway = "yes";
									//System.out.println("\n OneWay");
								}
								if (TagAttrs.item(j + 1).getNodeValue().equals("true")) {
									oneway = "yes";
									//System.out.println("\n OneWay");
								}

							}
						}
					}
				} //end // scan each <way> for <tag>s
				if (maxspeedFound) {
					lineOut = lineOut + ",maxspeed," + maxSpeed;
				}

				if (roundabout) {
					wayType = wayType + "roundabout";
				}
				if (wayType.isEmpty()) {
					wayType = "normal";
				}

				float lonLatPairs[][] = new float[4][2];
				int ndCount = 0;
				int nodestartends[] = new int[4];
				// loop thru way childnodes to find mappoint refs and lookup
				// lon/lat
				String nodelist = "";
				System.out.println("Child Nodes: " + listOfWaysChildNodes.getLength());
				System.out.println("Scan for <nd> nodes");
				for (int i = 0; i < listOfWaysChildNodes.getLength(); i++) {
					if (listOfWaysChildNodes.item(i).getNodeName().equals("nd")) {
						NamedNodeMap TagAttrs = listOfWaysChildNodes.item(i)
								.getAttributes();

						for (int j = 0; j < TagAttrs.getLength(); j++) {
							if ((TagAttrs.item(j).getNodeName()).equals("ref")) {
								// lineOut += "," + ndCount + "," +
								// Integer.parseInt(TagAttrs.item(j).getNodeValue());
								nodelist += " "
										+ TagAttrs.item(j).getNodeValue();
								if (ndCount == 0) {
									nodestartends[ndCount] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
									nodestartends[ndCount + 3] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
								} else if (ndCount == 1) {
									nodestartends[ndCount] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
									nodestartends[ndCount + 1] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
								}
								if (ndCount > 1) {
									nodestartends[3] = nodestartends[2];
									nodestartends[2] = Integer
											.parseInt(TagAttrs.item(j)
													.getNodeValue());
								}
								// lineOut += "," +
								// TagAttrs.item(j).getNodeValue();
							}// end checking for ref tags
						} // end looping thru nd tags
						ndCount += 1;
					}
				} // end loop thru way childnodes to find mappoint refs and
					// lookup lon/lat
				// lineOut += ",ndcount=" + ndCount;
				nodelist = nodelist.trim();
				for (ndCount = 0; ndCount < 4; ndCount++) {
					for (int k = 0; k < mapPoints.size(); k++) {
						if (mapPoints.get(k).getid() == nodestartends[ndCount]) {
							lonLatPairs[ndCount][0] = mapPoints.get(k).getlon();
							lonLatPairs[ndCount][1] = mapPoints.get(k).getlat();
							// lineOut = lineOut + "," +
							// mapPoints.get(k).getlon()+ "," +
							// mapPoints.get(k).getlat();
							// lineOut += "," + nodestartends[ndCount];
						}
					}
				}
				// Calc sign bearing

				double longDist;
				double latDist;
				double longDistDegrees = 0;
				double latDistDegrees = 0;
				longDistDegrees = (Double.valueOf(lonLatPairs[1][0])
						.doubleValue())
						- (Double.valueOf(lonLatPairs[0][0]).doubleValue());
				latDistDegrees = (Double.valueOf(lonLatPairs[1][1])
						.doubleValue())
						- (Double.valueOf(lonLatPairs[0][1]).doubleValue());

				longDist = (longDistDegrees * Math
						.cos((Float.valueOf(lonLatPairs[1][1]).floatValue()) * 3.1415926 / 180.0));
				latDist = (latDistDegrees);
				int angleToSign = (int) ((180 / 3.1415926) * Math.atan2(
						(double) latDist, (double) longDist));
				angleToSign = AngleToCompass(angleToSign);
				// int eduAngleToSign = Math.abs((int)((180/3.1415926) *
				// Math.atan2((double)latDist,(double)longDist)) - 90 +
				// Bearing);

				double longDist2;
				double latDist2;
				double longDistDegrees2 = 0;
				double latDistDegrees2 = 0;
				longDistDegrees2 = (Double.valueOf(lonLatPairs[3][0])
						.doubleValue())
						- (Double.valueOf(lonLatPairs[2][0]).doubleValue());
				latDistDegrees2 = (Double.valueOf(lonLatPairs[3][1])
						.doubleValue())
						- (Double.valueOf(lonLatPairs[2][1]).doubleValue());

				longDist2 = (longDistDegrees2 * Math
						.cos((Float.valueOf(lonLatPairs[1][1]).floatValue()) * 3.1415926 / 180.0));
				latDist2 = (latDistDegrees2);
				int angleToSign2 = (int) ((180 / 3.1415926) * Math.atan2(
						(double) latDist2, (double) longDist2));
				angleToSign2 = AngleToCompass(angleToSign2);

				// end calc sign bearing
				if (((maxspeedFound))) { // && (!roundabout))) { // && ((wayID
											// == 4119635) || (wayID ==
											// 4119634))) {
					String lineOutFinal = lineOut + "," + nodestartends[0]
							+ "," + nodestartends[1] + "," + angleToSign + ","
							+ AngleToDirection(angleToSign) + "," + wayType
							+ "," + nodelist + "," + nodestartends[2]+ "," + oneway;
					bw.write(lineOutFinal);
					System.out.println(s + ": " + lineOutFinal);
					bw.newLine();
				}

			}// end of for loop with s var
			bw.flush();
			bw.close();

		} catch (SAXParseException err) {
			System.out.println("** Parsing error" + ", line "
					+ err.getLineNumber() + ", uri " + err.getSystemId());
			System.out.println(" " + err.getMessage());

		} catch (SAXException e) {
			Exception x = e.getException();
			((x == null) ? e : x).printStackTrace();

		} catch (Throwable t) {
			t.printStackTrace();
		}

		

	}// end of main
	
	public static void InitialiseEliminate() {
		File file = new File(
				dirName + "/mapmaxspeeds_"
						+ filePartName + ".csv");

		try {

			BufferedReader bufRdr = new BufferedReader(new FileReader(file));
			String lineOut = null;
			// read each line of text file
			System.out.println("Reading csv into ways arraylist");
			while ((lineOut = bufRdr.readLine()) != null) {
				ways.add(lineOut);
				System.out.println("Reading " + (ways.size() - 1) + " : "
						+ lineOut);
			}
			bufRdr.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		for (int mainLoop = 0; mainLoop < (ways.size()); mainLoop++) {
			eliminate.add("Keep");
		}
	}

	public static void GenerateSpeedSignData() {

		AddToInfo("Check nodes for speed changes");
		jProgressBar1.setMaximum(ways.size());
		ArrayList<Integer> mainNodeList = new ArrayList<Integer>();
		ArrayList<Integer> checkNodeList = new ArrayList<Integer>();
		speedSigns.clear();

		int currWaysSize = ways.size();
		for (int mainLoop = 0; mainLoop < (currWaysSize); mainLoop++) { // loop through all the ways
			jProgressBar1.setValue(mainLoop);
			MaxSpeedWay line = new MaxSpeedWay(ways.get(mainLoop));

			System.out.println("Checking main " + mainLoop + " : " + ways.get(mainLoop));
			
			StringTokenizer stNodeList = new StringTokenizer(line.getnodelist(), " ");
			mainNodeList.clear();
			while (stNodeList.hasMoreElements()) {  // get all nodes in the main way
				mainNodeList.add(Integer.parseInt(stNodeList.nextToken()));
			}
			
			for (int mainNodeLoop = 0; mainNodeLoop < mainNodeList.size(); mainNodeLoop++) { // loop through all nodes of the main way looking for modes from other ways
				int mainNode = mainNodeList.get(mainNodeLoop); // get currrent main node
//				System.out.println("loop/node: " + mainLoop + " / " + mainNode);
				
				for (int innerLoop = 0; innerLoop < currWaysSize; innerLoop++) {// loop thru the ways again to check for speed changes
					MaxSpeedWay checkLine = new MaxSpeedWay(ways.get(innerLoop));
//					System.out.println("...inner " + innerLoop +": " + ways.get(innerLoop));
					if ((line.getwayID() != checkLine.getwayID())) { // don't compare the same way to itself
						if ((line.getspeedValue() != checkLine.getspeedValue())) { // dont bother if ways are the same speed
							if ((checkLine.getnodelist()).indexOf(Integer.toString(mainNode)) > -1) { // the ways join at some node so futher processing needed
								
								stNodeList = new StringTokenizer(checkLine.getnodelist(), " ");
								checkNodeList.clear();
								while (stNodeList.hasMoreElements()) {//get all the nodes from the check way
									checkNodeList.add(Integer.parseInt(stNodeList.nextToken()));
								}
								for (int checkNodeLoop = 0; checkNodeLoop < checkNodeList.size(); checkNodeLoop++) {// loop thru all nodes in the check way
									int checkNode = checkNodeList.get(checkNodeLoop);
									if (checkNode == mainNode) { // find the check node that matches with the main node
										int mainNodeLastNode =  mainNodeList.get(mainNodeList.size()-1);//save a bit of typing my remembering the last node of the main way
										int mainNodeFirstNode =  mainNodeList.get(0);//save a bit of typing my remembering the last node of the main way
										
//										int checkNodeLastNode =  checkNodeList.get(checkNodeList.size()-1);//save a bit of typing my remembering the last node of the main way
										int checkNodeFirstNode =  checkNodeList.get(0);//save a bit of typing my remembering the last node of the main way
										System.out.println(mainLoop + " / " + innerLoop + " / " + mainNode + " - " + checkNode);
										if ((mainNode != mainNodeLastNode)) {//this code executed if the main node is not an end node
											if (!((checkLine.getoneWay().equals("yes")) && (checkNode == checkNodeFirstNode))){
												AddNewSpeedSign(line.getwayID(),line.getspeedValue(),mainNode,mainNodeList.get(mainNodeLoop+1),"forward:"+line.getwayID());
											}
											if (!((mainNode == mainNodeFirstNode) || (line.getoneWay().equals("yes")))){
												AddNewSpeedSign(line.getwayID(),line.getspeedValue(),mainNode,mainNodeList.get(mainNodeLoop-1),"reverse:"+line.getwayID());
											}

										} else {
											if (!((mainNode == mainNodeFirstNode) || (line.getoneWay().equals("yes")))){
												AddNewSpeedSign(line.getwayID(),line.getspeedValue(),mainNode,mainNodeList.get(mainNodeLoop-1),"reverse end:"+line.getwayID());
											}
										}
									}
								}//end for checkNodeLoop
							}// end if are any nodes in common
						}// end if ways are same speed
					}// end if are any nodes in common
				}// end for

			} //end while
		}
//		System.exit(0);
		
		BufferedWriter bw;
		try {
			String mapSpeedSigns = dirName+ "/mapspeedsigns_" + filePartName + ".csv";
			@SuppressWarnings("unused")
			boolean success = (new File(mapSpeedSigns)).delete();
			bw = new BufferedWriter(new FileWriter(mapSpeedSigns, true), 8);

			for (int loop = 0; loop < (speedSigns.size()); loop++) {
				System.out.println(loop + ": " + speedSigns.get(loop));
				bw.write(loop + "," + speedSigns.get(loop));
				bw.newLine();
			}
			bw.flush();
			bw.close();

		} catch (Throwable t) {
			t.printStackTrace();
		}
		
	} //end



	public static void WriteKMLFile() {

		try {
			// create signs KML file first
			BufferedWriter bw = null;
			String mapNodes = dirName + "/osm_signs_"
					+ filePartName + ".kml";
			@SuppressWarnings("unused")
			boolean success = (new File(mapNodes)).delete();
			bw = new BufferedWriter(new FileWriter(mapNodes, true), 8);
			bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			bw.newLine();
			bw
					.write("<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\" xmlns:kml=\"http://www.opengis.net/kml/2.2\" xmlns:atom=\"http://www.w3.org/2005/Atom\">");
			bw.newLine();
			bw.write("<Document>\n");

			bw.write("<Style id=\"maxspeed20\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[20])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed25\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[25])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed30\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[30])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed35\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[35])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed40\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[40])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed45\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[45])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed50\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[50])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed55\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[55])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed60\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[60])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed65\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[65])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed70\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[70])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed75\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[75])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed80\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[80])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");

			for (int loop = 0; loop < (speedSigns.size()); loop++) {
				SpeedSign line = new SpeedSign(speedSigns.get(loop));

				System.out.println(loop + ": " + speedSigns.get(loop));
				float lon = 0;
				float lat = 0;
				float lon2 = 0;
				float lat2 = 0;
				
				for (int k = 0; k < mapPoints.size(); k++) {
					if (mapPoints.get(k).getid() == line.getsecondNode()) {
						lon2 = mapPoints.get(k).getlon();
						lat2 = mapPoints.get(k).getlat();
					}
				}
				
				for (int k = 0; k < mapPoints.size(); k++) {
					if (mapPoints.get(k).getid() == line.getfirstNode()) {
						lon = mapPoints.get(k).getlon();
						lat = mapPoints.get(k).getlat();
					}
				}
				if ((lon >= lhEdge) && (lon < (lhEdge + 0.1))
						&& (lat >= botEdge) && (lat < (botEdge + 0.1))) {
					bw.write("<Placemark>\n\t<name>" + line.getspeedValue());
					
					double longDist = ((lon2-lon) * Math.cos((lat * 3.1415926 / 180.0)));
					double latDist = (lat2-lat);
					int angleToSign = (int) ((180 / 3.1415926) * Math.atan2(
							(double) latDist, (double) longDist));
					angleToSign = AngleToCompass(angleToSign);
					
					bw.write(" " + angleToSign);
					bw.write(" " + line.getcomment());
					bw.write("</name>\n");
					bw.write("\t\t<description>" + speedSigns.get(loop)
							+ "</description>\n");
					bw.write("\t\t<Point>\n\t\t\t<coordinates>" + lon + ","
							+ lat + ",0</coordinates>\n\t\t</Point>\n");
					bw.write("</Placemark>");
					bw.newLine();
				}
			}// end of mainLoop

			
			bw.write("</Document>\n");
			bw.write("</kml>");
			bw.flush();
			bw.close();
			// end of creating sign kml file

			// draw ways themselves
			mapNodes = dirName + "/osm_ways_"
					+ filePartName + ".kml";
			success = (new File(mapNodes)).delete();
			bw = new BufferedWriter(new FileWriter(mapNodes, true), 8);
			bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			bw.newLine();
			bw
					.write("<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\" xmlns:kml=\"http://www.opengis.net/kml/2.2\" xmlns:atom=\"http://www.w3.org/2005/Atom\">");
			bw.newLine();
			bw.write("<Document>\n");

			bw.write("<Style id=\"maxspeed20\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[20])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed25\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[25])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed30\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[30])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed35\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[35])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed40\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[40])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed45\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[45])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed50\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[50])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed55\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[55])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed60\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[60])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed65\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[65])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed70\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[70])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed75\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[75])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw.write("<Style id=\"maxspeed80\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[80])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");

			int lastWayID = 0;
			for (int mainLoop = 0; mainLoop < (ways.size()); mainLoop++) {
				MaxSpeedWay line = new MaxSpeedWay(ways.get(mainLoop));

				if ((line.getwayID() != lastWayID)
						&& !(line.getauthor().equals("TJUNCADD"))) {
					lastWayID = line.getwayID();
					System.out.println(mainLoop + ": " + ways.get(mainLoop));

					int lineSpeedValue = line.getspeedValue();
					bw.write("<Placemark>\n\t<name>" + lineSpeedValue + " "
							+ line.getbearing() + "</name>\n");
					if (lineSpeedValue == 20)
						bw.write("\t<styleUrl>#maxspeed20</styleUrl>\n");
					if (lineSpeedValue == 25)
						bw.write("\t<styleUrl>#maxspeed25</styleUrl>\n");
					if (lineSpeedValue == 30)
						bw.write("\t<styleUrl>#maxspeed30</styleUrl>\n");
					if (lineSpeedValue == 35)
						bw.write("\t<styleUrl>#maxspeed35</styleUrl>\n");
					if (lineSpeedValue == 40)
						bw.write("\t<styleUrl>#maxspeed40</styleUrl>\n");
					if (lineSpeedValue == 45)
						bw.write("\t<styleUrl>#maxspeed45</styleUrl>\n");
					if (lineSpeedValue == 50)
						bw.write("\t<styleUrl>#maxspeed50</styleUrl>\n");
					if (lineSpeedValue == 55)
						bw.write("\t<styleUrl>#maxspeed55</styleUrl>\n");
					if (lineSpeedValue == 60)
						bw.write("\t<styleUrl>#maxspeed60</styleUrl>\n");
					if (lineSpeedValue == 65)
						bw.write("\t<styleUrl>#maxspeed60</styleUrl>\n");
					if (lineSpeedValue == 70)
						bw.write("\t<styleUrl>#maxspeed70</styleUrl>\n");
					if (lineSpeedValue == 75)
						bw.write("\t<styleUrl>#maxspeed75</styleUrl>\n");
					if (lineSpeedValue == 80)
						bw.write("\t<styleUrl>#maxspeed80</styleUrl>\n");
					bw
							.write("\t<LineString>\n\t\t<tessellate>1</tessellate>\n\t\t<coordinates>");
					StringTokenizer stNodeList = new StringTokenizer(line
							.getnodelist(), " ");
					String wayLonLat = "";
					while (stNodeList.hasMoreElements()) {
						if (wayLonLat.length() > 0) {
							wayLonLat = wayLonLat + ",";
						}
						int lookupNode = Integer.parseInt(stNodeList
								.nextToken());
						float lon = 0;
						float lat = 0;
						for (int k = 0; k < mapPoints.size(); k++) {
							if (mapPoints.get(k).getid() == lookupNode) {
								lon = mapPoints.get(k).getlon();
								lat = mapPoints.get(k).getlat();
							}
						}
						wayLonLat = wayLonLat + lon + "," + lat + ",0";
					}
					bw.write(wayLonLat + "</coordinates>\n\t</LineString>\n");
					bw.write("</Placemark>");
					bw.newLine();
				}
			}// end of mainLoop

			bw.write("</Document>\n");
			bw.write("</kml>");
			bw.flush();
			bw.close();
			
			// draw tails
			mapNodes = dirName + "/osm_tails_"
					+ filePartName + ".kml";
			success = (new File(mapNodes)).delete();
			bw = new BufferedWriter(new FileWriter(mapNodes, true), 8);
			bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			bw.newLine();
			bw
					.write("<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\" xmlns:kml=\"http://www.opengis.net/kml/2.2\" xmlns:atom=\"http://www.w3.org/2005/Atom\">");
			bw.newLine();
			bw.write("<Document>\n");

			bw
					.write("<Style id=\"maxspeed20\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[20])+"</color>\n<width>9</width>\n</LineStyle>\n</Style>\n");
			bw
					.write("<Style id=\"maxspeed30\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[30])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw
					.write("<Style id=\"maxspeed40\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[40])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw
					.write("<Style id=\"maxspeed50\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[50])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw
					.write("<Style id=\"maxspeed60\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[60])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");
			bw
					.write("<Style id=\"maxspeed70\">\n<LineStyle>\n<color>"+Integer.toHexString(0x7F000000 | kmlPalette[70])+"</color>\n<width>10</width>\n</LineStyle>\n</Style>\n");

			lastWayID = 0;
			for (int mainLoop = 0; mainLoop < (speedSigns.size()); mainLoop++) {
				SpeedSign line = new SpeedSign(speedSigns.get(mainLoop));

				lastWayID = line.getwayID();
				System.out.println(mainLoop + ": " + speedSigns.get(mainLoop));

				int lineSpeedValue = line.getspeedValue();
				bw.write("<Placemark>\n\t<name>" + lineSpeedValue + "</name>\n");
				if (lineSpeedValue == 20)
						bw.write("\t<styleUrl>#maxspeed20</styleUrl>\n");
				if (lineSpeedValue == 30)
						bw.write("\t<styleUrl>#maxspeed30</styleUrl>\n");
				if (lineSpeedValue == 40)
						bw.write("\t<styleUrl>#maxspeed40</styleUrl>\n");
				if (lineSpeedValue == 50)
						bw.write("\t<styleUrl>#maxspeed50</styleUrl>\n");
				if (lineSpeedValue == 60)
						bw.write("\t<styleUrl>#maxspeed60</styleUrl>\n");
				if (lineSpeedValue == 70)
						bw.write("\t<styleUrl>#maxspeed70</styleUrl>\n");
				bw.write("\t<LineString>\n\t\t<tessellate>1</tessellate>\n\t\t<coordinates>");

				String wayLonLat = "";
				int lookupNode = line.getfirstNode();
				float lon = 0;
				float lat = 0;
				for (int k = 0; k < mapPoints.size(); k++) {
					if (mapPoints.get(k).getid() == lookupNode) {
						lon = mapPoints.get(k).getlon() + (float) Math.random()/50000;
						lat = mapPoints.get(k).getlat() + (float) Math.random()/50000;
					}
				}
				wayLonLat = lon + "," + lat + ",0";
				
				lookupNode = line.getsecondNode();
				lon = 0;
				lat = 0;
				for (int k = 0; k < mapPoints.size(); k++) {
					if (mapPoints.get(k).getid() == lookupNode) {
						lon = mapPoints.get(k).getlon() + (float) Math.random()/50000;
						lat = mapPoints.get(k).getlat() + (float) Math.random()/50000;
					}
				}
				wayLonLat = wayLonLat + "," + lon + "," + lat + ",0";
				
				bw.write(wayLonLat + "</coordinates>\n\t</LineString>\n");
				bw.write("</Placemark>");
				bw.newLine();
			}// end of mainLoop

			bw.write("</Document>\n");
			bw.write("</kml>");
			bw.flush();
			bw.close();

			// write maxspeed way kml file

		} catch (IOException e) {
			e.printStackTrace();
		} catch (Throwable t) {
			t.printStackTrace();
		}

	}// end of main

/*
	public static void addLine(String s) {
		BufferedWriter bw;
		try {
			bw = new BufferedWriter(new FileWriter(
					dirName + "/mapnode_"
							+ filePartName + ".csv", true), 8);
			bw.write(s);
			bw.newLine();
			bw.flush();
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
*/
	public static void readMapPoints() {
		File file = new File(dirName + "/mapnodes_"	+ filePartName + ".csv");

		try {
			Mappoint singlePoint = null;
			BufferedReader bufRdr = new BufferedReader(new FileReader(file));
			String line = null;
			// read each line of text file
			while ((line = bufRdr.readLine()) != null) {
				StringTokenizer st = new StringTokenizer(line, ",");

				int id = Integer.parseInt(st.nextToken());
				float lon = Float.valueOf(st.nextToken()).floatValue();
				float lat = Float.valueOf(st.nextToken()).floatValue();

				// System.out.println(id + " : " + lon + " : " + lat);
				singlePoint = new Mappoint(id, lon, lat);

				mapPoints.add(singlePoint);

			}
			bufRdr.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// close the file
		for (int i = 0; i < mapPoints.size() - 1; i++) {
			// System.out.println(mapPoints.get(i).getid() + " : " +
			// mapPoints.get(i).getlon() + " : " + mapPoints.get(i).getlat() );
		}
	}

	public static String AngleToDirection(int angle) {
		String direction = "NN";
		angle = (angle + 360) % 360;
		if (angle >= 338)
			direction = "NN";
		else if ((angle < 337) && (angle >= 293))
			direction = "NW";
		else if ((angle < 292) && (angle >= 248))
			direction = "WW";
		else if ((angle < 247) && (angle >= 203))
			direction = "SW";
		else if ((angle < 202) && (angle >= 158))
			direction = "SS";
		else if ((angle < 157) && (angle >= 113))
			direction = "SE";
		else if ((angle < 112) && (angle >= 68))
			direction = "EE";
		else if ((angle < 67) && (angle >= 23))
			direction = "NE";
		else if ((angle < 22) && (angle >= 0))
			direction = "NN";

		return direction;
	}

	public static int AngleToCompass(int angle) {
		return (360 - angle + 90) % 360;
	}

	
	public static void MakeMap() {
		jProgressBar1.setMaximum(ways.size());
		g.setColor(new Color(255, 255, 255) );
		g.fillRect ( 0, 0, image.getWidth(), image.getHeight() );
		for (int y =0;y<imageScale;y+=2) {
			for (int x =0;x<imageScale;x+=2) {
//				image.setRGB(x, y, 0xE0E0E0);
			}
		}

		g2d.setColor(new Color(255,255,255));
		g2d.fillRect(0, 0, imageScale, imageScale);
		

		AddToInfo("Drawing all highways");
	
		File file = new File(dirName + "/map_highways_"	+ filePartName + ".csv");
		try {
			BufferedReader bufRdr = new BufferedReader(new FileReader(file));
			String lineOut = null;
			// read each line of text file
			while ((lineOut = bufRdr.readLine()) != null) {
	//			jProgressBar1.setValue(mainLoop);
				MaxSpeedWay line = new MaxSpeedWay(lineOut);
				if (!(line.getauthor().equals("TJUNCADD"))) {
	//				System.out.println(mainLoop + ": " + ways.get(mainLoop));
					int lineSpeedValue = line.getspeedValue();
					Color lineSpeedColor = new Color(0,0,0);
					if ((lineSpeedValue >= 20)) {
						lineSpeedColor = new Color((palette[lineSpeedValue]& 0xFF0000) >> 16,(palette[lineSpeedValue]& 0xFF00) >> 8,(palette[lineSpeedValue]& 0xFF) );
					}
					StringTokenizer stNodeList = new StringTokenizer(line.getnodelist(), " ");
					String wayLonLat = "";
					int lookupNode = Integer.parseInt(stNodeList.nextToken());
					float lon = 0;
					float lat = 0;
					for (int k = 0; k < mapPoints.size(); k++) {
						if (mapPoints.get(k).getid() == lookupNode) {
							lon = mapPoints.get(k).getlon() - (float)lhEdge;
							lat = mapPoints.get(k).getlat() - (float)botEdge;
						}
					}
					wayLonLat = lon + "," + lat;
					System.out.println("Move cursor to: " + wayLonLat);
					float startLon = lon;
					float startLat = lat;
		
					while (stNodeList.hasMoreElements()) {
						if (wayLonLat.length() > 0) {
							wayLonLat = wayLonLat + ",";
						}
						lookupNode = Integer.parseInt(stNodeList.nextToken());
						lon = 0;
						lat = 0;
						for (int k = 0; k < mapPoints.size(); k++) {
							if (mapPoints.get(k).getid() == lookupNode) {
								lon = mapPoints.get(k).getlon() - (float)lhEdge;
								lat = mapPoints.get(k).getlat() - (float)botEdge;
							}
						}
						wayLonLat = lon + "," + lat;
		
						double lonDiff = (lon - startLon)*imageScale*10;
						double latDiff = (lat - startLat)*imageScale*10;
						double diag = Math.sqrt(lonDiff*lonDiff + latDiff*latDiff);
		
						double deltaX = lonDiff / diag;
						double deltaY = latDiff / diag;
//						System.out.println(mainLoop + " :Drawline in " + lineSpeedColor + " to: " +wayLonLat + " using " + diag + ": "+ deltaX +" , " + deltaY);
						//					g.drawLine((int)(startLon*imageScale*10),imageScale-(int)(startLat*imageScale*10), (int)(lon*imageScale*10),imageScale-(int)(lat*imageScale*10));
						g2d.setColor(lineSpeedColor);
						//					g2d.setXORMode(new Color(255,255,255));
	//					g2d.setStroke(new BasicStroke(5F,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
	//					g2d.setStroke(new BasicStroke(5F,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
						if (line.getspeedValue() <= 30){
							g2d.setStroke(new BasicStroke(1F,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND));
						} else {
							g2d.setStroke(new BasicStroke(1F,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND));
	//						g2d.setColor(new Color(0xFF,0x00,0xFF));
						}
	//					g2d.setStroke(new BasicStroke(5F,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND));
						if (line.getspeedValue() <= 30) {
	//						g2d.drawLine((int)(startLon*imageScale*10),imageScale-(int)(startLat*imageScale*10), (int)(lon*imageScale*10),imageScale-(int)(lat*imageScale*10));
						}
						g2d.drawLine((int)(startLon*imageScale*10),imageScale-(int)(startLat*imageScale*10), (int)(lon*imageScale*10),imageScale-(int)(lat*imageScale*10));
	
						if (0<=lon && lon < 0.1 && 0<=lat && lat < 0.1) {
							int range = 2;
							int lonPix = Math.max(range,(int)(lon*imageScale*10));
							lonPix = Math.min(imageScale-range-1,lonPix);
							int latPix = Math.max(range,(int)(imageScale - (lat*imageScale*10)));
							latPix = Math.min(imageScale-range-1,latPix);
	
							for (int y=-range;y<=range;y++){
								for (int x=-range;x<=range;x++){
									if (image.getRGB(lonPix + x, latPix + y) != lineSpeedColor.getRGB()){
	//									image.setRGB(lonPix + x, latPix + y,0);
									}
								}	
							}
						}
				
						startLon = lon;
						startLat = lat;
		
					}
	
				}// end tjunc if
				myImage = new ImageIcon(image.getScaledInstance(myLabel.getWidth(), myLabel.getHeight(), 1));
				myLabel.setIcon(myImage);
	            myLabel.getParent().repaint();
	            myLabel.getParent().validate();
			}// end of mainLoop
			bufRdr.close();
		} catch (IOException e) {
			e.printStackTrace();
		} // end try
		
		//====== loop  for again for speeds > 0 and <= 30 =========================================
		AddToInfo("Drawing ways > 0 and <= 30mph");
		for (int mainLoop = 0; mainLoop < (ways.size()); mainLoop++) {
			jProgressBar1.setValue(mainLoop);
			MaxSpeedWay line = new MaxSpeedWay(ways.get(mainLoop));
			if (!(line.getauthor().equals("TJUNCADD"))) {
				System.out.println(mainLoop + ": " + ways.get(mainLoop));
	
				int lineSpeedValue = line.getspeedValue();
				Color lineSpeedColor = new Color(0,0,0);
				if ((lineSpeedValue >= 20)) {
					lineSpeedColor = new Color((palette[lineSpeedValue]& 0xFF0000) >> 16,(palette[lineSpeedValue]& 0xFF00) >> 8,(palette[lineSpeedValue]& 0xFF) );
				}

				StringTokenizer stNodeList = new StringTokenizer(line.getnodelist(), " ");
				String wayLonLat = "";
				int lookupNode = Integer.parseInt(stNodeList.nextToken());
				float lon = 0;
				float lat = 0;
				for (int k = 0; k < mapPoints.size(); k++) {
					if (mapPoints.get(k).getid() == lookupNode) {
						lon = mapPoints.get(k).getlon() - (float)lhEdge;
						lat = mapPoints.get(k).getlat() - (float)botEdge;
					}
				}
				wayLonLat = lon + "," + lat;
				System.out.println("Move cursor to: " + wayLonLat);
				float startLon = lon;
				float startLat = lat;
	
				while (stNodeList.hasMoreElements()) {
					if (wayLonLat.length() > 0) {
						wayLonLat = wayLonLat + ",";
					}
					lookupNode = Integer.parseInt(stNodeList.nextToken());
					lon = 0;
					lat = 0;
					for (int k = 0; k < mapPoints.size(); k++) {
						if (mapPoints.get(k).getid() == lookupNode) {
							lon = mapPoints.get(k).getlon() - (float)lhEdge;
							lat = mapPoints.get(k).getlat() - (float)botEdge;
						}
					}
					wayLonLat = lon + "," + lat;
	
					double lonDiff = (lon - startLon)*imageScale*10;
					double latDiff = (lat - startLat)*imageScale*10;
					double diag = Math.sqrt(lonDiff*lonDiff + latDiff*latDiff);
	
					double deltaX = lonDiff / diag;
					double deltaY = latDiff / diag;
					System.out.println(mainLoop + " :Drawline in " + lineSpeedColor + " to: " +wayLonLat + " using " + diag + ": "+ deltaX +" , " + deltaY);
					//					g.drawLine((int)(startLon*imageScale*10),imageScale-(int)(startLat*imageScale*10), (int)(lon*imageScale*10),imageScale-(int)(lat*imageScale*10));

					//					g2d.setXORMode(new Color(255,255,255));
//					g2d.setStroke(new BasicStroke(5F,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND));
					if ((lineSpeedValue > 0) && (lineSpeedValue <= 30)) {
						g2d.setStroke(new BasicStroke(3F,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
						g2d.setColor(lineSpeedColor);
						g2d.drawLine((int)(startLon*imageScale*10),imageScale-(int)(startLat*imageScale*10), (int)(lon*imageScale*10),imageScale-(int)(lat*imageScale*10));
				
						if (0<=lon && lon < 0.1 && 0<=lat && lat < 0.1) {
							int range = 2;
							int lonPix = Math.max(range,(int)(lon*imageScale*10));
							lonPix = Math.min(imageScale-range-1,lonPix);
							int latPix = Math.max(range,(int)(imageScale - (lat*imageScale*10)));
							latPix = Math.min(imageScale-range-1,latPix);

							for (int y=-range;y<=range;y++){
								for (int x=-range;x<=range;x++){
									if (image.getRGB(lonPix + x, latPix + y) != lineSpeedColor.getRGB()){
//										image.setRGB(lonPix + x, latPix + y,0x7F000000);
									}
								}	
							}
						}
					}
					


					startLon = lon;
					startLat = lat;
				}
			}// end tjunc if
			myImage = new ImageIcon(image.getScaledInstance(myLabel.getWidth(), myLabel.getHeight(), 1));
			myLabel.setIcon(myImage);
            myLabel.getParent().repaint();
            myLabel.getParent().validate();
		}// end of mainLoop doing > 0 and <= 30 mph
		
		
		
		//====== loop again for speeds > 30 =========================================
		AddToInfo("Drawing ways > 30mph");
		for (int mainLoop = 0; mainLoop < (ways.size()); mainLoop++) {
			jProgressBar1.setValue(mainLoop);
			MaxSpeedWay line = new MaxSpeedWay(ways.get(mainLoop));
			if (!(line.getauthor().equals("TJUNCADD"))) {
				System.out.println(mainLoop + ": " + ways.get(mainLoop));
	
				int lineSpeedValue = line.getspeedValue();
				Color lineSpeedColor = new Color(0,0,0);
				if ((lineSpeedValue >= 20)) {
					lineSpeedColor = new Color((palette[lineSpeedValue]& 0xFF0000) >> 16,(palette[lineSpeedValue]& 0xFF00) >> 8,(palette[lineSpeedValue]& 0xFF) );
				}

				StringTokenizer stNodeList = new StringTokenizer(line.getnodelist(), " ");
				String wayLonLat = "";
				int lookupNode = Integer.parseInt(stNodeList.nextToken());
				float lon = 0;
				float lat = 0;
				for (int k = 0; k < mapPoints.size(); k++) {
					if (mapPoints.get(k).getid() == lookupNode) {
						lon = mapPoints.get(k).getlon() - (float)lhEdge;
						lat = mapPoints.get(k).getlat() - (float)botEdge;
					}
				}
				wayLonLat = lon + "," + lat;
				System.out.println("Move cursor to: " + wayLonLat);
				float startLon = lon;
				float startLat = lat;
	
				while (stNodeList.hasMoreElements()) {
					if (wayLonLat.length() > 0) {
						wayLonLat = wayLonLat + ",";
					}
					lookupNode = Integer.parseInt(stNodeList.nextToken());
					lon = 0;
					lat = 0;
					for (int k = 0; k < mapPoints.size(); k++) {
						if (mapPoints.get(k).getid() == lookupNode) {
							lon = mapPoints.get(k).getlon() - (float)lhEdge;
							lat = mapPoints.get(k).getlat() - (float)botEdge;
						}
					}
					wayLonLat = lon + "," + lat;
	
					double lonDiff = (lon - startLon)*imageScale*10;
					double latDiff = (lat - startLat)*imageScale*10;
					double diag = Math.sqrt(lonDiff*lonDiff + latDiff*latDiff);
	
					double deltaX = lonDiff / diag;
					double deltaY = latDiff / diag;
					System.out.println(mainLoop + " :Drawline in " + lineSpeedColor + " to: " +wayLonLat + " using " + diag + ": "+ deltaX +" , " + deltaY);
					//					g.drawLine((int)(startLon*imageScale*10),imageScale-(int)(startLat*imageScale*10), (int)(lon*imageScale*10),imageScale-(int)(lat*imageScale*10));

					//					g2d.setXORMode(new Color(255,255,255));
//					g2d.setStroke(new BasicStroke(5F,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND));
					if ((lineSpeedValue > 30)) {
						g2d.setStroke(new BasicStroke(3F,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
						g2d.setColor(lineSpeedColor);
						g2d.drawLine((int)(startLon*imageScale*10),imageScale-(int)(startLat*imageScale*10), (int)(lon*imageScale*10),imageScale-(int)(lat*imageScale*10));
				
						if (0<=lon && lon < 0.1 && 0<=lat && lat < 0.1) {
							int range = 2;
							int lonPix = Math.max(range,(int)(lon*imageScale*10));
							lonPix = Math.min(imageScale-range-1,lonPix);
							int latPix = Math.max(range,(int)(imageScale - (lat*imageScale*10)));
							latPix = Math.min(imageScale-range-1,latPix);

							for (int y=-range;y<=range;y++){
								for (int x=-range;x<=range;x++){
									if (image.getRGB(lonPix + x, latPix + y) != lineSpeedColor.getRGB()){
//										image.setRGB(lonPix + x, latPix + y,0x7F000000);
									}
								}	
							}
						}
					}
					


					startLon = lon;
					startLat = lat;
				}
			}// end tjunc if
			myImage = new ImageIcon(image.getScaledInstance(myLabel.getWidth(), myLabel.getHeight(), 1));
			myLabel.setIcon(myImage);
            myLabel.getParent().repaint();
            myLabel.getParent().validate();
		}// end of mainLoop doing > 30 mph

		
		
		// =========== check color around a node
		AddToInfo("Check Color around every node");
		for (int mainLoop = 0; mainLoop < (ways.size()); mainLoop++) {
			jProgressBar1.setValue(mainLoop);
			MaxSpeedWay line = new MaxSpeedWay(ways.get(mainLoop));

			System.out.println(mainLoop + ": Mway points " + ways.get(mainLoop));
			int lineSpeedValue = line.getspeedValue();
			Color lineSpeedColor = new Color(0,0,0);
			if ((lineSpeedValue >= 20)) {
				lineSpeedColor = new Color((palette[lineSpeedValue]& 0xFF0000) >> 16,(palette[lineSpeedValue]& 0xFF00) >> 8,(palette[lineSpeedValue]& 0xFF) );
			}


			StringTokenizer stNodeList = new StringTokenizer(line.getnodelist(), " ");
			while (stNodeList.hasMoreElements()) {
				int lookupNode = Integer.parseInt(stNodeList.nextToken());
	
				float lon = 0;
				float lat = 0;
				for (int k = 0; k < mapPoints.size(); k++) {
					if (mapPoints.get(k).getid() == lookupNode) {
						lon = mapPoints.get(k).getlon() - (float)lhEdge;
						lat = mapPoints.get(k).getlat() - (float)botEdge;
					}
				}

	
//				if (eliminate.get(mainLoop).equals("Keep")) {
					if ((line.getspeedValue() > 30) && !line.getauthor().equals("TJUNCADD")){
						if (0<=lon && lon < 0.1 && 0<=lat && lat < 0.1) {
							int range = 3;
							int lonPix = Math.max(range,(int)(lon*imageScale*10));
							lonPix = Math.min(imageScale-range-1,lonPix);
							int latPix = Math.max(range,(int)(imageScale - (lat*imageScale*10)));
							latPix = Math.min(imageScale-range-1,latPix);
	
							for (int y=-range;y<=range;y++){
								for (int x=-range;x<=range;x++){
									if (image.getRGB(lonPix + x, latPix + y) != lineSpeedColor.getRGB()) {
										if (image.getRGB(lonPix + x, latPix + y) != -1) {
											image.setRGB(lonPix + x, latPix + y,0xFF000000);
										} else {
//											image.setRGB(lonPix + x, latPix + y,lineSpeedColor.getRGB());
										}
//										image.setRGB(lonPix + x, latPix + y,0xFFD0D0D0);
									}
								}	
							}

				 

						}
					}
//				} // endif elim
			} // end while


			myImage = new ImageIcon(image.getScaledInstance(myLabel.getWidth(), myLabel.getHeight(), 1));
			myLabel.setIcon(myImage);
            myLabel.getParent().repaint();
            myLabel.getParent().validate();
		}// end of 1 dot per node

	
		
		try {    
			ImageIO.write(image, "png", new File(dirName + "/map_" + filePartName + ".png"));   
		} catch (IOException e) {    
			e.printStackTrace();   
		} 

//		System.exit(0);
	}
	
	public static void AddToInfo (String text) {
		infoTextArea.append(text + "\n");
        infoTextArea.setCaretPosition(infoTextArea.getDocument().getLength()); 
        infoTextArea.repaint();
        infoTextArea.validate();
		
	}

	public static void MakeTiles() {
		divisions = 2;
		for (int tiley=0;tiley<(divisions);tiley+=1) {		
			for (int tilex=0;tilex<(divisions);tilex+=1) {
				for (int y =0;y<(imageScale / divisions);y+=1) {
					for (int x =0;x<(imageScale / divisions);x+=1) {
						tiledImage.setRGB(x, y, image.getRGB(x +(tilex*(imageScale / divisions)), y +(tiley*(imageScale / divisions))));
					}
				}
				try {   
					longPartName = filePartName.substring(0,5);
					String longDir = longPartName.substring(0,1);
					int longEdge = 10000 + Integer.parseInt(longPartName.substring(1,5));
					longEdge = (longEdge*10) - (int)(10*((float)tilex / (float)divisions));
					String longEdgePartName = longDir+ Integer.toString(longEdge).substring(1,6);
					
					latPartName = filePartName.substring(6,11);
					String latDir = latPartName.substring(0,1);
					int latEdge = 10000 + Integer.parseInt(latPartName.substring(1,5));
					latEdge = (latEdge*10) + ((10 - (int)(10*((float)1 / (float)divisions))) - (int)(10*((float)tiley / (float)divisions)));
					String latEdgePartName = latDir+ Integer.toString(latEdge).substring(1,6);

					ImageIO.write(tiledImage, "png", new File(dirName + "/map_" + longEdgePartName + "_" + latEdgePartName + ".png"));   
				} catch (IOException e) {    
					e.printStackTrace();   
				} 

			}
		}
	}
	
	public static void AddNewSpeedSign(int wayID,int speedValue,int firstNode,int secondNode,String comment) {
		int speedSignsOldSize = speedSigns.size();
		boolean okToAdd = true;
		for (int loop=0;loop<speedSignsOldSize;loop++) {
			SpeedSign storedSign = new SpeedSign(speedSigns.get(loop));
			if ((storedSign.getfirstNode() == firstNode) && (storedSign.getsecondNode() == secondNode)) {
				
				okToAdd = false;
			}
			
		} // end for
		if (okToAdd) {
			speedSigns.add(wayID+","+speedValue+","+firstNode+","+secondNode+","+comment);
		}

	}
	
}
